/* $RCSFile: ADNUrlBuilderProvider.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/ADNCRM.UrlBuilderProvider.Implementation/ADNUrlBuilderProvider.cs $
 * $log$
 * Revision 6 2010/08/06 19:56:31  christian.surieux
 *   Added Log to All cs files
 */

using System;
using System.Diagnostics;
using System.Collections;
using System.Configuration;
using System.Configuration.Provider;
using System.Collections.Specialized;
using System.Text;
using System.Threading;
using System.Web;
using System.Web.Caching;
using System.Globalization;

using AddonNice.Settings;
using AddonNice.Configuration;

namespace AddonNice.Web
{
	/// <summary>
	/// Addon Nice standard implementation for rewriting urls
    /// Generate normally an url for the url rewritter
    /// This process could be stopped by setting UseRewrittenUrls=false in web.config
	/// </summary>
	public class ADNUrlBuilderProvider : UrlBuilderProvider
	{
		private string _defaultSplitter         =   "__";
		private string _handlerFlag             =   string.Empty;
		private bool _aliasInUrl                =   false;
		private bool _langInUrl                 =   false;
		private string _ignoreTargetPage        =   string.Empty;//"pagelayout.aspx";
		//private double _cacheMinutes            =   5;
		bool _pageidNoSplitter                  =   false;
		private string _friendlyPageName        =   Config.DefaultModulesPage;
        bool UseRewrittenUrls                   =   Config.UseRewrittenUrls;


		public ADNUrlBuilderProvider()
		{
            if ( ProviderTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNUrlBuilderProvider Provider started: {0}", DateTime.UtcNow),ProviderTraceSwitch.Sw.Info);
		}

		public override void Initialize(string name, NameValueCollection configValue) 
		{
            if ( ProviderTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNUrlBuilderProvider Provider initialize {0}: {1}", name, DateTime.UtcNow),ProviderTraceSwitch.Sw.Info);
            base.Initialize(name, configValue);
            // For legacy support first check provider settings then web.config legacy settings
			if (configValue["handlersplitter"] != null)
			{
				_defaultSplitter    =   configValue["handlersplitter"].ToString();
			}
			else
			{
				_defaultSplitter    =   Config.HandlerDefaultSplitter;
			}
            if ( ProviderTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNUrlBuilderProvider Initialize _defaultSplitter: {0}",_defaultSplitter),ProviderTraceSwitch.Sw.Info);

			if (configValue["handlerflag"] != null)
			{
				_handlerFlag        =   configValue["handlerflag"].ToString();
			}
			else
			{
				_handlerFlag        =   Config.HandlerFlag;
			}
            if ( ProviderTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNUrlBuilderProvider Initialize _handlerFlag: {0}",_handlerFlag),ProviderTraceSwitch.Sw.Info);

			if (configValue["aliasinurl"] != null)
			{
				_aliasInUrl         =   bool.Parse(configValue["aliasinurl"].ToString());
			}
			else
			{
					_aliasInUrl     =   Config.UseAlias;
			}
            if ( ProviderTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNUrlBuilderProvider Initialize _aliasInUrl: {0}",_aliasInUrl),ProviderTraceSwitch.Sw.Info);

			if (configValue["langinurl"] != null)
			{
				_langInUrl          =   bool.Parse(configValue["langinurl"].ToString());
			}
			else
			{
				_langInUrl          =   Config.LangInURL;
			}
            if ( ProviderTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNUrlBuilderProvider Initialize _langInUrl: {0}",_langInUrl),ProviderTraceSwitch.Sw.Info);

			if ( configValue["ignoretargetpage"] != null )
			{
				_ignoreTargetPage   =   configValue["ignoretargetpage"].ToString();
			}
            if ( ProviderTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNUrlBuilderProvider Initialize _ignoreTargetPage: {0}",_ignoreTargetPage),ProviderTraceSwitch.Sw.Info);
            /*
			if (configValue["cacheminutes"] != null)
			{
				_cacheMinutes       =   Convert.ToDouble(configValue["cacheminutes"].ToString());
			}
            if ( ProviderTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNUrlBuilderProvider Initialize _cacheMinutes: {0}",_cacheMinutes),ProviderTraceSwitch.Sw.Info);
            */
			if (configValue["pageidnosplitter"] != null)
			{
				_pageidNoSplitter   =   bool.Parse(configValue["pageidnosplitter"].ToString());
			}
            if ( ProviderTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNUrlBuilderProvider Initialize _pageidNoSplitter: {0}",_pageidNoSplitter),ProviderTraceSwitch.Sw.Info);

			if (configValue["friendlypagename"] != null)
			{
				_friendlyPageName   =   configValue["friendlypagename"].ToString();
			}
            if ( ProviderTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNUrlBuilderProvider Initialize _friendlyPageName: {0}",_friendlyPageName),ProviderTraceSwitch.Sw.Info);
		}
		
		/// <summary> 
		/// Takes a Page ID and builds the url for the desidered page (non default)
		/// containing the application path, portal alias, tab ID, and language. 
        /// When the targetPage param starts with ~/, build a full path url with scheme according PortalIsSecure portal setting
        /// So to be sure to have the correct http scheme, use a target page starting with ~/
		/// </summary> 
		/// <param name="PageLoc">Where this page should be loaded</param> 
		/// <param name="targetPage">Linked page</param> 
        /// <param name="KeepTargetPage">Keep target page</param> 
		/// <param name="pageID">ID of the page</param> 
		/// <param name="modID">ID of the module</param> 
		/// <param name="culture">Client culture</param> 
		/// <param name="customAttributes">Any custom attribute that can be needed. Use the following format...single attribute: paramname--paramvalue . Multiple attributes: paramname--paramvalue/paramname2--paramvalue2/paramname3--paramvalue3 </param> 
		/// <param name="currentAlias">Current Alias</param> 
		/// <param name="urlKeywords">Add some keywords to uniquely identify this tab. Usual source is UrlKeyword from TabSettings.</param> 
		public override string BuildUrl(string targetPage,bool KeepTargetPage,DynPageLoc PageLoc, int pageID, int modID, CultureInfo culture, string customAttributes, string currentAlias, string urlKeywords)
		{
			bool _isPlaceHolder		        =   false;
			string _tabLink			        =   string.Empty;
			string _urlKeywords		        =   string.Empty;
			string _pageName		        =   _friendlyPageName;

			if ( ProviderTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNUrlBuilderProvider BuildUrl targetPage: '{0}', keepTargetPage: {1}, PageLoc: {2}, pageID: {3}, modID: {4}, culture: {5}, customAttributes: {6}, currentAlias: {7}, urlKeywords: {8}",
                    new object[]{targetPage,KeepTargetPage,PageLoc,pageID, modID, culture.Name, customAttributes, currentAlias, urlKeywords}),ProviderTraceSwitch.Sw.Info);

			// Get Url Elements this helper method (Will either retrieve from cache or database)
			ADNUrlBuilderHelper.GetUrlElements(pageID,ref _isPlaceHolder, ref _tabLink, ref _urlKeywords, ref _pageName);
            if ( ProviderTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNUrlBuilderProvider BuildUrl _isPlaceHolder: {0}, _tabLink: {1}, _urlKeywords: {2}, _pageName: {3}",
                    new object[]{_isPlaceHolder, _tabLink, _urlKeywords, _pageName}),ProviderTraceSwitch.Sw.Info);
			
            // Do not modify URLs when working with PageLayout Administration Page ????? usage TBC
			// Removed 26/08/09 CS if ( !(targetPage.ToLower().EndsWith(_ignoreTargetPage.ToLower())) ) 
			{
				// if it is a placeholder it is not supposed to have any url
				if (_isPlaceHolder) 
                    return string.Empty;
				
				// if it is a tab link it means it is a link to an external resource
                if (_tabLink.Length != 0)
                {
                    if (ProviderTraceSwitch.Sw.TraceVerbose)
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNUrlBuilderProvider BuildUrl return _tabLink: {0}", _tabLink), ProviderTraceSwitch.Sw.Info);
                    return _tabLink;
                }
			}

            StringBuilder sb                =   new StringBuilder();

			// Obtain ApplicationPath
			if ( targetPage.StartsWith("~/") )
			{
				string app	                =	ADNUrlBuilderHelper.ApplicationFullPath.ToLower();
				if ( app.EndsWith("/") )
					app	                    =	app.Substring(0,app.Length-1);
				targetPage					=	targetPage.Substring(2);
				string tg					=	targetPage.ToLower();
				string[] PortalSecuredDirs	=	ADNUrlBuilderHelper.PortalSecuredDirs;
				if ( ProviderTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNUrlBuilderProvider BuildUrl app: {0}, PortalIsSecured: {1} ",app,ADNUrlBuilderHelper.PortalIsSecured),ProviderTraceSwitch.Sw.Info);
                
                // When portal is secured, transform any secured folder from http to https url
				
                const string strhttp        =   "http";
                const string strhttps       =   "https";
                const string strhttpquote   =   "http:";
                const string strhttpsquote  =   "https:";
                if ( ADNUrlBuilderHelper.PortalIsSecured )
				{
                    bool fnd                =   false;
                    if ( PageLoc != DynPageLoc.Normal )
                        fnd                 =   true;
					else
                    {
                        foreach(string str in PortalSecuredDirs)
					    {
						    if ( str == string.Empty )
							    continue;
						    if ( tg.StartsWith(str.ToLower()+'/') )
                            {
                                fnd         =   true;
                                break;
                            }
                        }
                    }
                    if ( fnd )
					{
						if ( app.StartsWith(strhttpquote) )
                            app	            =	strhttps+ app.Substring(4);
						else if ( !app.StartsWith(strhttpsquote) )
							app	            =	strhttpsquote+app;
						if ( ProviderTraceSwitch.Sw.TraceVerbose )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNUrlBuilderProvider BuildUrl Secured portal forcing secure dir to https app: '{0}'",app),ProviderTraceSwitch.Sw.Info);
					}
                    else 
					{
						// if portal is admin we keep https
                        if ( app.StartsWith(strhttpsquote) )
                        {
                            if ( !Config.IsAdminPortal )
                                app	        =	strhttp+ app.Substring(5);
                        }
						else if ( !app.StartsWith(strhttpquote) )
							app	            =	strhttpquote+app;
						if ( ProviderTraceSwitch.Sw.TraceVerbose )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNUrlBuilderProvider BuildUrl Secured portal not secured folder resetting to http app: '{0}'",app),ProviderTraceSwitch.Sw.Info);
					}
				}
				// When portal is NOT secured, transform any folder from https to http url
				else
				{
					if ( app.StartsWith(strhttpsquote) )
                        app	                =	strhttp+ app.Substring(5);
					else if ( !app.StartsWith(strhttpquote) )
						app	                =	strhttpquote+app;
					if ( ProviderTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNUrlBuilderProvider BuildUrl Not Secured portal not secured folder app: {0}",app),ProviderTraceSwitch.Sw.Info);
				}
				sb.Append(app);
			}
			
			sb.Append("/");

			if (!targetPage.EndsWith(".aspx") && !targetPage.EndsWith(".ascx")) //Images
			{
				sb.Append(targetPage);
				string str	=	sb.ToString();
                if ( ProviderTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNUrlBuilderProvider BuildUrl END special target page: {0}, result= {1}",targetPage,str),ProviderTraceSwitch.Sw.Info);
				return str;
			}

            const string locMark            =   "pl";
            const string locMarkSpecial     =   "pls";
            string locM                     =   (KeepTargetPage) ? locMarkSpecial:locMark;

            // Separate path
			// If page contains path, or it is not an aspx 
			// or handlerFlag is not set: do not use handler build a conventionnal url not for url rewritter
			if ( !UseRewrittenUrls  
                || ( _handlerFlag.Length == 0 )
				|| targetPage.LastIndexOf('/') > 0 // All properties or Add/Edit pages should go here
				|| (!targetPage.EndsWith(".aspx") && !targetPage.EndsWith(".ascx") )  // CS Added usage-> loading acsx
				)
			{
                if (ProviderTraceSwitch.Sw.TraceVerbose)
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNUrlBuilderProvider BuildUrl building normal url UseRewrittenUrls: {0}, targetPage: {1}",
                        UseRewrittenUrls,targetPage), ProviderTraceSwitch.Sw.Info);
				// Add pageID to URL, insert any special path according to PageLoc param
                switch ( PageLoc )
                {
                    default:
                    case DynPageLoc.Normal:
                    sb.AppendFormat("{0}?pageid={1}",targetPage,pageID);
                    break;

                    case DynPageLoc.Login:
					sb.AppendFormat("{0}/{1}?pageid={2}",LoginPage,targetPage,pageID);
                    break;

                    case DynPageLoc.Secured:
					sb.AppendFormat("{0}/{1}?pageid={2}",SecurePage,targetPage,pageID);
                    break;
                }

				// Add Alias to URL
				if (_aliasInUrl)
				{
					sb.AppendFormat("&alias={0}",currentAlias); // changed for compatibility with handler
				}

				// Add ModID to URL
				if (modID > 0)
				{
					sb.AppendFormat("&mid={0}",modID);
				}

				// Add Language to URL
				if (_langInUrl)
				{
					sb.AppendFormat("&lang={0}",culture.Name); // changed for compatibility with handler
				}


				// Add custom attributes
				if ( !string.IsNullOrEmpty(customAttributes) )
				{
					sb.Append("&");
					customAttributes        =   customAttributes.Replace("/", "&");
					customAttributes        =   customAttributes.Replace(_defaultSplitter, "=");
					sb.Append(customAttributes);
				}
				string str	                =	sb.ToString().Replace("&&", "&");
                if ( str.StartsWith("//") ) // 1/6/09 avoid any // due to a targetpage as "/TargetPageUrl..."
                    str                     =   str.Substring(1);
                if ( ProviderTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNUrlBuilderProvider BuildUrl END result= {0}", str),ProviderTraceSwitch.Sw.Info);
				return str;
			}
			// Add smarturl tag
			sb.AppendFormat("{0}/",_handlerFlag);

			// Add custom Keywords to the Url
			if (string.IsNullOrEmpty(urlKeywords) )
				urlKeywords = _urlKeywords;
                
            if ( !string.IsNullOrEmpty(urlKeywords) )
            {
				sb.AppendFormat("{0}/",urlKeywords);
			}

			// Add Alias to URL
			if (_aliasInUrl)
			{
				sb.AppendFormat("alias{0}{1}/",_defaultSplitter,currentAlias);
			}

			// Add Language to URL
			if (_langInUrl)
			{
				sb.AppendFormat("lang{0}{1}/",_defaultSplitter,culture.Name);
			}
			// Add ModID to URL
			if (modID > 0)
			{
				sb.AppendFormat("mid{0}{1}/",_defaultSplitter,modID);
			}
            switch ( PageLoc )
            {
                default:
                case DynPageLoc.Normal:
                break;

                case DynPageLoc.Login:
				sb.AppendFormat("{0}{1}{2}/",locM,_defaultSplitter,LoginPage); 
                break;

                case DynPageLoc.Secured:
				sb.AppendFormat("{0}{1}{2}/",locM,_defaultSplitter,SecurePage); 
                break;
            }
			
            // Add custom attributes
		    if ( !string.IsNullOrEmpty(customAttributes) )
			{
				customAttributes            =   customAttributes.ToString().Replace("&", "/");
				customAttributes            =   customAttributes.ToString().Replace("=", _defaultSplitter);
				sb.Append(customAttributes);
				sb.Append("/");
			}

			if(_pageidNoSplitter)
			{
				sb.AppendFormat("{0}/",pageID);
			}
			else
			{
				// Add pageID to URL
				sb.AppendFormat("pageid{0}{1}/",_defaultSplitter,pageID);
			}

			if ( targetPage == DefaultPage )
				    sb.Append(_pageName);
			else	sb.Append(targetPage);
			// avoid any misplaced // due to targetpage starting with '/'
			string	wpat	                =	sb.ToString().Replace("//","/");
			// replace incorrectly changed value
			wpat			                =	wpat.Replace(":/","://");
            if ( ProviderTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNUrlBuilderProvider BuildUrl END smart url result= {0}", wpat),ProviderTraceSwitch.Sw.Info);
			return wpat;
		}
		
        /// <summary> 
		/// Determines if a tab is simply a placeholder in the navigation
		/// </summary> 
		public override bool IsPlaceholder(int pageID)
		{
			return (bool)ADNUrlBuilderHelper.PageSpecificProperty(pageID, ADNUrlBuilderHelper.IsPlaceHolderID);
		}

		/// <summary> 
		/// Returns the URL for a tab that is a link only.
		/// </summary> 
		public override string TabLink(int pageID)
		{
			return (string)ADNUrlBuilderHelper.PageSpecificProperty(pageID, ADNUrlBuilderHelper.TabLinkID);
		}

		/// <summary> 
		/// Returns any keywords which are meant to be placed in the url
		/// </summary> 
		public override string UrlKeyword(int pageID)
		{
			return (string)ADNUrlBuilderHelper.PageSpecificProperty(pageID, ADNUrlBuilderHelper.UrlKeywordsID);
		}

		/// <summary> 
		/// Returns the page name that has been specified. 
		/// </summary> 
		public override string UrlPageName(int pageID)
		{
			string _urlPageName     =   (string)ADNUrlBuilderHelper.PageSpecificProperty(pageID, ADNUrlBuilderHelper.PageNameID);

			if ( string.IsNullOrEmpty(_urlPageName) )
				_urlPageName        =   _friendlyPageName;

			return _urlPageName;
		}

		/// <summary>
		/// Gets the default page from web.config
		/// </summary>
		public override string DefaultPage
		{
			get
			{
                return Config.HandlerTargetUrl;
			}
		}


		public override string LoginPage
		{
			get
			{
                return Config.PortalLogonDirectory;
			}
		}

        public override string SecurePage
		{
			get
			{
                return Config.PortalSecureDirectory;
			}
		}



		/// <summary>
		/// Returns the default paramater splitter from provider settings (or web.config/rainbow.config if not specified in provider) 
		/// </summary>
		public override string DefaultSplitter
		{
			get
			{
				return _defaultSplitter;
			}
		}

		/// <summary> 
		/// Clears the cached url element settings
		/// </summary> 
		public override void Clear(int pageID)
		{
			ADNUrlBuilderHelper.ClearUrlElements(pageID);
		}
	}
}
